home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Tech Arsenal 1
/
Tech Arsenal (Arsenal Computer).ISO
/
tek-01
/
cljul90.zip
/
COLORFUN.C
< prev
next >
Wrap
Text File
|
1990-04-18
|
17KB
|
626 lines
/*
* colorfun.c
* X Window demo program that draws a colored box
* in a window. Every second, we change the color.
*
* To compile and run this program, you
* will need to link in the X library
* (usually called Xlib), usually done with
* a command something like:
*
* cc -o colorfun colorfun.c -lX11
*
* (On UNIX systems.)
*
* Note that we use some functions found only
* in the Release 4 Xlib. These functions are
* marked as such, so if you have an R3 or
* older system you can easily convert.
*
* Written for Computer Language magazine
* by E F Johnson and K Reichard, 1990.
*
*/
#include <stdio.h>
/*
* Most X programs will need Xlib.h and Xutil.h
*/
#include <X11/Xlib.h>
#include <X11/Xutil.h>
main( argc, argv )
int argc;
char *argv[];
{ /* -- main */
Display *display;
int screen;
Window window;
GC gc;
int done;
XColor the_color;
Visual *visual;
int depth;
XFontStruct *font;
int status;
Colormap colormap;
unsigned long black, white;
/*
* 1) Set up X display connection with the server
* named in the user's DISPLAY environment variable.
*/
display = XOpenDisplay( NULL );
if ( display == (Display *) NULL )
{
(void) fprintf( stderr, "Error: Could not open display\n" );
exit( 1 );
}
/*
* 2) Find a visual that supports color and get its depth.
*/
screen = DefaultScreen( display );
SetUpVisual( display, screen, &visual, &depth );
/*
* 3a) Create Color map and get a black and white
* pixel values for the colormap.
*/
SetUpColormap( display, screen, visual, &colormap, &black, &white );
/*
* 3b) Allocate one read-write color cell.
*/
status = XAllocColorCells( display, colormap,
False, NULL, 0, &the_color.pixel, 1 );
if ( status == 0 )
{
(void) fprintf( stderr, "Error in allocating color cell.\n" );
XCloseDisplay( display );
exit( 1 );
}
/*
* Set up some "random" RGB color values.
*/
the_color.red = ( 1 << 8 );
the_color.green = ( 104 << 8 );
the_color.blue = ( 200 << 8 );
/*
* 4) Load a font
*/
font = XLoadQueryFont( display, "fixed" );
if ( font == (XFontStruct *) NULL )
{
(void) fprintf( stderr, "Error loading fixed font\n" );
XCloseDisplay( display );
exit( 1 );
}
/*
* 5) Create a window and set ICCCM values.
*/
SetUpWindow( display, visual, depth, colormap, black, white, &window );
/*
* 6) Create a graphics context (GC) for our window.
*/
gc = XCreateGC( display, window, 0x0, (XGCValues *) NULL );
XSetFont( display, gc, font->fid );
XSetBackground( display, gc, white );
/*
* 7) "Map" our window, making it appear
* on the screen.
*/
XMapRaised( display, window );
XFlush( display );
/*
* 8) Loop on events, exit on a ButtonPress event.
*/
done = False;
while( !done )
{
done = CheckForEvents( display, window, gc,
&the_color, black );
/*
* 9) Sleep for a second,
* to space out the color changes.
*/
sleep( 1 );
/*
* 10) Change the color in our window.
*/
ChangeColor( display, colormap, &the_color );
/*
* 11) Redraw with the new color
*/
Redraw( display, window, gc, &the_color, black );
}
/*
* 12) Free/Destroy our window, GC, and font.
*/
XDestroyWindow( display, window );
XFreeGC( display, gc );
XFreeFont( display, font );
/*
* 13) Close our X display connection and quit.
*/
XCloseDisplay( display );
exit( 0 );
} /* -- main */
CheckForEvents( display, window, gc, the_color, black )
Display *display;
Window window;
GC gc;
XColor *the_color;
unsigned long black;
/*
* 8) Loop on events.
* CheckForEvents() checks to see if an X event
* is pending. If so, CheckForEvents() reads in
* that event and then acts on it (perhaps by
* doing nothing). We ignore changes to the window's
* size (it is assumed the user will be too
* dazzled by the program to even think about resizing
* the window).
*/
{ /* -- function CheckForEvents */
XEvent event;
int done = False;
/*
* 8a) Do we have an event waiting?
*/
if ( XPending( display ) > 0 )
{
XNextEvent( display, &event );
switch( event.type )
{
/*
* 8b) Set a flag if a mouse button
* is pressed. We will exit later.
*/
case ButtonPress:
done = True;
break;
/*
* 8c) Only redraw our window when
* the last Expose event comes in.
*/
case Expose:
if ( event.xexpose.count == 0 )
{
Redraw( display, window,
gc, the_color, black );
}
break;
}
}
return( done );
} /* -- function CheckForEvents */
Redraw( display, window, gc, the_color, black )
Display *display;
Window window;
GC gc;
XColor *the_color;
unsigned long black;
/*
* Redraw() redraws our window. Redraw()
* is called whenever the window's contents
* need to be refreshed, because the contents
* have changed, or because the window system
* requests we redraw the window due to "damage".
*/
{ /* -- function Redraw */
char string[ 120 ];
/*
* Fill in a rectangle, in the given color.
*/
XSetForeground( display, gc, the_color->pixel );
XFillRectangle( display, window, gc,
10, 30, 200, 100 );
/*
* Draw text in black
*/
XSetForeground( display, gc, black );
/*
* Display current color values as text
*/
(void) sprintf( string, "R 0x%5.5x G 0x%5.5x B 0x%5.5x",
the_color->red,
the_color->green,
the_color->blue );
XDrawImageString( display, window, gc,
10, 20,
string, strlen( string ) );
/*
* Send output requests to the X server
*/
XFlush( display );
} /* -- function Redraw */
SetUpColormap( display, screen, visual, colormap, black, white )
Display *display;
int screen;
Visual *visual;
Colormap *colormap;
unsigned long *black, *white;
/*
* SetUpColormap() creats an X colormap using the
* given screen and visual. Color cells (pixels)
* for "black" and "white" are also allocated in
* our new colormap.
*/
{ /* -- function SetUpColormap */
int status;
XColor hardwarecolor, exactcolor;
/*
* Create a colormap using the
* visual found in SetUpVisual().
*/
*colormap = XCreateColormap( display,
RootWindow( display, screen ),
visual,
AllocNone );
/*
* Check for failure.
*/
if ( *colormap != None )
{
/* -- Set up "white" in the new colormap */
status = XAllocNamedColor( display, *colormap, "white",
&hardwarecolor,
&exactcolor );
if ( status != 0 )
{
*white = hardwarecolor.pixel;
/* -- Set up "black" in the new colormap */
status = XAllocNamedColor( display, *colormap, "black",
&hardwarecolor,
&exactcolor );
*black = hardwarecolor.pixel;
}
}
else
{
status = 0;
}
if ( status == 0 )
{
(void) fprintf( stderr, "Error in creating colormap\n" );
XCloseDisplay( display );
exit( 1 );
}
} /* -- function SetUpColormap */
SetUpVisual( display, screen, visual, depth )
Display *display;
int screen;
Visual **visual;
int *depth;
/*
* SetUpVisual() finds a PseudoColor visual
* on the given screen. If none is to be found,
* the program will terminate. *depth is set to
* the depth of the found visual.
*/
{ /* -- function SetUpVisual */
int number_visuals;
XVisualInfo *visual_array, visual_template;
/*
* We want a PseudoColor visual on this screen.
* XGetVisualInfo() will get a list of all
* the PseudoColor visuals supported on
* this screen.
*/
visual_template.class = PseudoColor;
visual_template.screen = screen;
visual_array = XGetVisualInfo( display,
VisualClassMask | VisualScreenMask,
&visual_template,
&number_visuals );
/* -- Check for success */
if ( ( number_visuals > 0 ) && ( visual_array != NULL ) )
{
/*
* We're lazy, we just choose the
* first PseudoColor visual
*/
*visual = visual_array[0].visual;
*depth = visual_array[0].depth;
XFree( visual_array );
}
else
{
(void) fprintf( stderr, "Error in finding visual\n" );
XCloseDisplay( display );
exit( 1 );
}
} /* -- function SetUpVisual */
SetUpWindow( display, visual, depth, colormap, fore, back, window )
Display *display;
Visual *visual;
int depth;
Colormap colormap;
unsigned long fore, back;
Window *window;
/*
* 5) Create a window. We need to be careful here
* to use our visual and colormap.
*/
{ /* -- function SetUpWindow */
int x, y, width, height;
XSetWindowAttributes attributes;
unsigned long attribute_mask;
int screen;
XWMHints *wmhints;
XSizeHints *sizehints;
/*
* 5a) Determine x, y, width, height. Normally
* in X, the user should be able to specify this
* on the UNIX command-line. For simplicity,
* we're just using arbitrary values here.
*/
x = 10;
y = 10;
width = 220;
height = 140;
/*
* 5b) Fill in a window attributes structure.
* fore and back arer the black and white colors
* allocated in our new colormap. If we use
* the default BlackPixel() and WhitePixel(),
* we may get strange values since these
* may not have been allocated in our new
* colormap.
*/
attributes.background_pixel = back;
attributes.border_pixel = fore;
attributes.event_mask = ExposureMask | ButtonPressMask;
attributes.colormap = colormap;
attribute_mask = CWBackPixel | CWBorderPixel |
CWEventMask | CWColormap;
/*
* 5c) Create window
*/
screen = DefaultScreen( display );
*window = XCreateWindow( display,
RootWindow( display, screen ), /* parent window */
x, y, width, height,
2, /* -- border width */
depth,
InputOutput, /* -- window class */
visual, /* -- our visual */
attribute_mask,
&attributes );
if ( *window == (Window) None )
{
(void) fprintf( stderr, "Error: could not open window\n" );
XCloseDisplay( display );
exit( 1 );
}
/*
* 5d) Store a name for the window
* with the window manager. Note we are
* using Latin-1 names, so users in Japan
* or Arabia might want to use X's compound
* text mechanism.
*/
XStoreName( display, *window, "ColorFun" );
/*
* 5e) Set window manager hints, R4-only functions!
*/
wmhints = XAllocWMHints();
if ( wmhints != NULL )
{
wmhints->initial_state = NormalState;
wmhints->input = True;
wmhints->flags = StateHint | InputHint;
XSetWMHints( display, *window, wmhints );
XFree( wmhints );
}
/*
* 5f) Set Size hints, again R4-specific!
* (This also requires an R4 or ICCCM-compliant
* window manager.)
*/
sizehints = XAllocSizeHints();
if ( sizehints != NULL )
{
sizehints->base_width = width;
sizehints->base_height = height;
sizehints->flags = PBaseSize;
XSetWMNormalHints( display, *window, sizehints );
XFree( sizehints );
}
} /* -- function SetUpWindow */
ChangeColor( display, colormap, color )
Display *display;
Colormap colormap;
XColor *color;
/*
* Every second, ChangeColor() is called to
* modify the current color we are displaying.
*/
{ /* -- function ChangeColor */
color->flags = DoRed | DoGreen | DoBlue;
color->red = (unsigned short) IncrementValue( color->red, 3 );
color->green = (unsigned short) IncrementValue( color->green, 6 );
color->blue = (unsigned short) IncrementValue( color->blue, 5 );
XStoreColor( display, colormap, color );
} /* -- function ChangeColor */
IncrementValue( value, amount )
short value;
int amount; /* -- add this amount to value. */
/*
* Some common 8-plane color systems seem to just
* use the upper byte of the color values for
* Red, Green and Blue (hence all the >> and <<
* bit-shift operations). If you don't like how
* these colors look on your system, change
* IncrementValue() and ChangeColor() to do what
* you'd like. Play around with them and have fun.
*/
{ /* -- function IncrementValue */
unsigned short new_value;
new_value = ( value >> 8 );
new_value += amount;
/*
* Spend more time with brighter colors.
*/
if ( new_value > 200 )
{
new_value--;
}
if ( new_value > 250 )
{
new_value = 0;
}
return( new_value << 8 );
} /* -- function IncrementValue */
/*
* end of file
*/